<script setup lang="ts">
import { onMounted, ref } from "vue";
import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import vertexShader from "./shader/vertex-shader/study-1.ts";
import fragmentShader from "./shader/fragment-shader/study-1.ts";
import Stats from "three/examples/jsm/libs/stats.module.js";

/* dom */
const container = ref<HTMLDivElement | null>(null);
/* data */
const clock = new THREE.Clock();
const resolution = ref<THREE.Vector2>(new THREE.Vector2(0.0, 0.0));

onMounted(() => {
    init();
});

const init = () => {
    const { clientWidth, clientHeight } = container.value as HTMLDivElement;
    resolution.value.set(clientWidth, clientHeight);
    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera(
        75,
        clientWidth / clientHeight,
        1,
        1000
    );
    camera.position.set(0, 0, 20);
    camera.lookAt(0, 0, 0);
    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(clientWidth, clientHeight);
    container.value?.appendChild(renderer.domElement);

    const helper = new THREE.AxesHelper(20);
    scene.add(helper);

    // 坐标
    const control = new OrbitControls(camera, renderer.domElement);

    // 状态显示
    const state = new Stats();
    document.body.appendChild(state.dom);

    const mesh = initBox(scene);

    function render() {
        mesh.material.uniforms.u_time.value = clock.getElapsedTime();

        control.update();
        state.update();
        renderer.render(scene, camera);
        requestAnimationFrame(render);
    }
    render();
};

const initBox = (
    scene: THREE.Scene
): THREE.Mesh<THREE.IcosahedronGeometry, THREE.ShaderMaterial> => {
    const material = new THREE.RawShaderMaterial({
        uniforms: {
            u_time: { value: clock.getElapsedTime() },
        },
        vertexShader,
        fragmentShader: fragmentShader,
        side: THREE.DoubleSide,
        transparent: true,
    });

    const geo = new THREE.IcosahedronGeometry(10, 5);

    const mesh = new THREE.Mesh(geo, material);

    scene.add(mesh);

    console.log(geo);

    return mesh;
};
</script>

<template>
    <div ref="container" class="container"></div>
</template>

<style lang="less" scoped>
.container {
    width: 100%;
    height: 100%;
}
</style>
